package com.byron.media.server.handlers;

import com.byron.media.server.config.MediaServerConfig;
import com.byron.media.server.enums.MediaType;
import com.byron.media.server.enums.ProxyType;
import com.byron.media.server.logic.HandlerContainer;
import com.byron.media.server.model.MediaData;
import com.byron.media.server.model.MediaHeaderObj;
import com.byron.media.server.model.ProxyMediaData;
import com.byron.media.server.sessions.*;
import com.byron.media.server.utils.JsonUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
//@ChannelHandler.Sharable
public class MediaServerHandler extends ChannelInboundHandlerAdapter {

    private MediaServerConfig config;        // 本机是否为proxyServer

    private AtomicInteger seq = new AtomicInteger(1);

    private long countLog = 0;

    public MediaServerHandler(MediaServerConfig config) {
        this.config = config;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        MediaSession session = ctx.pipeline().get(MediaSession.class);
//        sessionContainer.addToGroup(session.session);
        if(config.isLog()){
            log.info("客户端【{}】上线", ctx.channel().remoteAddress().toString());
            log.error("客户端【{}】上线", ctx.channel().remoteAddress().toString());
        }
        super.channelActive(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RealSession realSession = ctx.pipeline().get(RealSession.class);
        if(msg instanceof MediaData){

            MediaData mediaData = (MediaData)msg;
            if(MediaType.isHeart(mediaData.getType())){
                ctx.fireChannelReadComplete();

                if(config.isLog()){
                    log.info("接收到来自【{}】的心跳", realSession.getClientSession().toString());
                }
                return;
            }

            if(realSession.isProxyServer()){
                log.error("代理服务器之间不应该发送 MediaData 信息");
                ctx.fireChannelReadComplete();
                return;
            }

            ISession session = realSession.getClientSession();
            if(session == null){
                return;
            }

            if(session.isActive()){
                if(config.isLog()){
                    countLog ++;
                    if(countLog % 100 == 0){
                        log.info("接收到来自【{}】的数据，大小【{}】", realSession.getClientSession().toString(), mediaData.getLength());
                    }
                }
                session.sendToOther(mediaData);
//                SessionContainer.getInstance().sendToOther(session, session.getGroupName(), mediaData);
            }

            // 代理数据
        } else if(msg instanceof ProxyMediaData){
            ProxyMediaData proxy = (ProxyMediaData)msg;
            if(proxy.getProxyType() == ProxyType.MEDIA_DATA){
                // 理论上不会收到代理的  mediaData
//                MediaData mediaData = proxy.getMediaData();
//                ISession session = SessionContainer.getInstance().getSessionById(mediaData.getID());
//                if(session.isActive()){
//                    SessionContainer.getInstance().sendToOther(session, proxy.getGroupName(), mediaData);
//                }
            } else if(proxy.getProxyType() == ProxyType.JSON){
                // 设备上线或离线消息
                MediaHeaderObj header = JsonUtils.fromJson(proxy.getJson(), MediaHeaderObj.class);

                String cmd = (String) header.getCmd().get("cmd");
                if(cmd == null){
                    return;
                }

                cmd = "proxy-" + cmd;

                HandlerContainer.getInstance().handle(cmd, realSession, ctx, header);
            }
        } else if(msg instanceof String){
            String json = (String) msg;
            MediaHeaderObj header = JsonUtils.fromJson(json, MediaHeaderObj.class);

            if(header.getCmd() == null){
                return;
            }

            String cmd = (String) header.getCmd().get("cmd");
            if(cmd == null){
                return;
            }

            HandlerContainer.getInstance().handle(cmd, realSession, ctx, header);
        }
        ctx.fireChannelReadComplete();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        log.error(cause.toString(), cause);
    }
}
